package activities;

import helper.FBHelper;
import helper.HttpHelper;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Queue;

import org.apache.http.HttpResponse;
import org.apache.http.ParseException;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.facebook.Response;
import com.facebook.Session;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.OnMyLocationChangeListener;
import com.google.android.gms.maps.MapFragment;
import com.matchcalendar.R;

import dataFormat.FBUser;
import dataFormat.IcultureActivity;
import fragments.NearActivitiesFragment;
import fragments.WhoHaveTimeFragment;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.location.Location;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.SparseArray;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;

public class ShakeActivity extends GlobalActivity {
	private SensorManager sensorManager;
	private ShakeSensorEventListener ssEventListener = new ShakeSensorEventListener();
	private LinearLayout rootView;
	private boolean haveShake = false;
	private Button buttonGoGroup;
	private List<Fragment> shakeFragmentsList = new ArrayList<Fragment>(2);
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.activity_shake);
		initGlobalView();
		findView();
		setListenerOrAdapter();
		getButtonShake().setEnabled(false);
		getButtonShake().setBackgroundResource(R.color.gray5);
		sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
	}
	
	private void findView() {
		rootView = (LinearLayout) findViewById(R.id.linearLayoutRoot);
		buttonGoGroup = (Button) findViewById(R.id.buttonGoGroup);
	}
	
	private void setListenerOrAdapter() {
		buttonGoGroup.setOnClickListener(new ButtonGoGroupClick());
	}
	
	private class ButtonGoGroupClick implements Button.OnClickListener {

		@Override
		public void onClick(View v) {
			WhoHaveTimeFragment whoHaveTimeFragment = (WhoHaveTimeFragment) shakeFragmentsList.get(0);
			NearActivitiesFragment nearAcFragment = (NearActivitiesFragment) shakeFragmentsList.get(1);
			FBUser selFriend = whoHaveTimeFragment.getSelFriend();
			IcultureActivity selAc = nearAcFragment.getSelAc();
			Bundle bundle = new Bundle();
			Intent intent = new Intent(ShakeActivity.this, AddMatchGroupActivity.class);
			
			if (selFriend == null && selAc == null) {
				new AlertDialog.Builder(ShakeActivity.this)
				.setTitle("選擇朋友或活動")
				.setMessage("請選擇一個朋友或活動")
				.setPositiveButton("好", null)
				.show();
			}
			else {
				bundle.putString("myFBID", getIntent().getExtras().getString("myFBID"));
				bundle.putInt("comeFrom", 2);
				if (selFriend != null && selAc == null) {
					bundle.putString("acStartTime", whoHaveTimeFragment.getSelStartTime());
					bundle.putString("acOverTime", whoHaveTimeFragment.getSelOverTime());
					bundle.putParcelable("friend", selFriend);
				}
				else if (selFriend == null && selAc != null) {
					String[] startEndTime = selAc.getTime().split("~");
					String[] startDateTime = startEndTime[0].split(" ");
					String[] overDateTime = startEndTime[1].split(" ");
					
					bundle.putString("title", selAc.getTitle());
					bundle.putString("location", selAc.getLocation());
					bundle.putString("matchStartDate", startDateTime[0]);
					bundle.putString("matchOverDate", overDateTime[0]);
				}
				else {
					String[] startEndTime = selAc.getTime().split("~");
					String[] startDateTime = startEndTime[0].split(" ");
					String[] overDateTime = startEndTime[1].split(" ");
					
					bundle.putString("title", selAc.getTitle());
					bundle.putString("location", selAc.getLocation());
					bundle.putString("matchStartDate", startDateTime[0]);
					bundle.putString("matchOverDate", overDateTime[0]);
					bundle.putString("acStartTime", whoHaveTimeFragment.getSelStartTime());
					bundle.putString("acOverTime", whoHaveTimeFragment.getSelOverTime());
					bundle.putParcelable("friend", selFriend);
				}
				intent.putExtras(bundle);
				startActivity(intent);
			}
		}
	}
	
	@Override
	protected void onResume() {
		super.onResume();
		if (!haveShake) {
			sensorManager.registerListener(ssEventListener,
					sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
		}
	}
	
	@Override
    protected void onPause() {
		super.onPause();
		sensorManager.unregisterListener(ssEventListener);
	}
	
	private class ShakeSensorEventListener implements SensorEventListener {
		private View resultView;
		private TextView textViewWhoHaveTime, textViewOver;
		private LinearLayout linearLayoutWhoHaveTimeColor, linearLayoutOverColor;
		private ViewPager shakeResultPager;
		private GoogleMap gMap;

		@Override
		public void onAccuracyChanged(Sensor arg0, int arg1) {
		}

		@Override
		public void onSensorChanged(SensorEvent event) {
			if (event.values[0] > 8 || event.values[0] < -8) {
				resultView = getLayoutInflater().inflate(R.layout.custom_after_shake_view, null);
				findView();
				setListenerOrAdapter();
				rootView.removeViewAt(1);
				rootView.addView(resultView);
				sensorManager.unregisterListener(this);
				haveShake = true;
				new GetMyFriendsFBHelper().ensureSessionOpenAndDoSomething(ShakeActivity.this);
			}
		}
		
		private void findView() {
			textViewWhoHaveTime = (TextView) resultView.findViewById(R.id.textViewWhoHaveTime);
			textViewOver = (TextView) resultView.findViewById(R.id.textViewOver);
			shakeResultPager = (ViewPager) resultView.findViewById(R.id.shakeResultPager);
			linearLayoutWhoHaveTimeColor = (LinearLayout)
					resultView.findViewById(R.id.linearLayoutWhoHaveTimeColor);
			linearLayoutOverColor = (LinearLayout) resultView.findViewById(R.id.linearLayoutOverColor);
			gMap = ((MapFragment)getFragmentManager().findFragmentById(R.id.gMap)).getMap();
		}
		
		private void setListenerOrAdapter() {
			textViewWhoHaveTime.setOnClickListener(new TextViewOptionClick(0));
			textViewOver.setOnClickListener(new TextViewOptionClick(1));
			shakeResultPager.setAdapter(new ShakeResultPagerAdapter(getSupportFragmentManager()));
			shakeResultPager.setOnPageChangeListener(new ShakeResultPagerPageChange());
		}
		
		private class TextViewOptionClick implements TextView.OnClickListener {
			private int index;

			public TextViewOptionClick(int index) {
				this.index = index;
			}

			@Override
			public void onClick(View v) {
				shakeResultPager.setCurrentItem(index);
			}
		}
		
		private class ShakeResultPagerAdapter extends FragmentStatePagerAdapter {
			public ShakeResultPagerAdapter(FragmentManager fm) {
				super(fm);
			}

			@Override
			public Fragment getItem(int index) {
				return shakeFragmentsList.get(index);
			}

			@Override
			public int getCount() {
				return shakeFragmentsList.size();
			}
			
			@Override
			public int getItemPosition(Object object) {
				return POSITION_NONE;
			}
		}
		
		private class ShakeResultPagerPageChange implements ViewPager.OnPageChangeListener {

			@Override
			public void onPageScrollStateChanged(int arg0) {
			}

			@Override
			public void onPageScrolled(int arg0, float arg1, int arg2) {
			}

			@Override
			public void onPageSelected(int index) {
				linearLayoutWhoHaveTimeColor.setBackgroundResource(R.color.white);
				linearLayoutOverColor.setBackgroundResource(R.color.white);
				if (index == 0)
					linearLayoutWhoHaveTimeColor.setBackgroundResource(R.color.gold1);
				else
					linearLayoutOverColor.setBackgroundResource(R.color.gold1);
			}
		}
		
		private class GetMyFriendsFBHelper extends FBHelper {
			private ProgressDialog proDialog;

			@Override
			protected void doAfterEnsureSessionOpen() {
				proDialog = ProgressDialog.show(ShakeActivity.this, "查詢中", "正在查看今天誰有空...");
				proDialog.setCancelable(false);
				fqlQuery("uid", "user", "uid in (select uid2 from friend where uid1 = me())", null,
						null, null, null);
			}

			@Override
			protected void doAfterFqlQuery(Response response) {
				try {
					JSONArray dataJsonArr = response.getGraphObject().getInnerJSONObject().getJSONArray("data");
					
					new PostFriendsHaveTimeToday().execute(dataJsonArr);
				} catch (JSONException e) {
					e.printStackTrace();
				}
			}
			
			private class PostFriendsHaveTimeToday extends AsyncTask<JSONArray, Void, String> {

				@Override
				protected String doInBackground(JSONArray... params) {
					String respJsonStr = null;
					
					try {
						JSONObject reqJsonObj = new JSONObject();
						JSONArray friendsJsonArr = new JSONArray();
						HttpResponse resp;
						
						for (int i=0; i<params[0].length(); i++) {
							String id = params[0].getJSONObject(i).getString("uid");
							
							friendsJsonArr.put(id);
						}
						reqJsonObj.put("friends", friendsJsonArr);
						resp = HttpHelper.executePost(
								"http://iculture.twgg.org/schedule/friendsHaveTimeToday.php", reqJsonObj.toString());
						respJsonStr = EntityUtils.toString(resp.getEntity());
					} catch (JSONException e) {
						e.printStackTrace();
					} catch (ParseException e) {
						e.printStackTrace();
					} catch (IOException e) {
						e.printStackTrace();
					}
					return respJsonStr;
				}
				
				@Override
				protected void onPostExecute(String respJsonStr) {
					try {
						JSONArray respJsonArr = new JSONArray(respJsonStr);
						Map<String, JSONObject> findTimeRangeJsonObj = new HashMap<String, JSONObject>();
						
						for (int i=0; i<respJsonArr.length(); i++) {
							JSONObject timeRangeJsonObj = respJsonArr.getJSONObject(i);
							
							findTimeRangeJsonObj.put(timeRangeJsonObj.getString("id"), timeRangeJsonObj);
						}
						if (respJsonArr.length() != 0) {
							String where = "uid = " + respJsonArr.getJSONObject(0).getString("id");
							
							for (int i=1; i<respJsonArr.length(); i++)
								where += " or uid = " + respJsonArr.getJSONObject(i).getString("id");
							new GetFriendsNameFBHelper(findTimeRangeJsonObj).fqlQuery("uid, name",
									"user", where, null, null, "name", null);
						}
					} catch (JSONException e) {
						e.printStackTrace();
					}
				}
				
				private class GetFriendsNameFBHelper extends FBHelper {
					private Map<String, JSONObject> findTimeRangeJsonObj;

					public GetFriendsNameFBHelper(Map<String, JSONObject> findTimeRangeJsonObj) {
						this.findTimeRangeJsonObj = findTimeRangeJsonObj;
					}

					@Override
					protected void doAfterEnsureSessionOpen() {
					}

					@Override
					protected void doAfterFqlQuery(Response response) {
						try {
							JSONArray dataJsonArr =
									response.getGraphObject().getInnerJSONObject().getJSONArray("data");
							List<FBUser> friendList = new ArrayList<FBUser>();
							SparseArray<JSONObject> positionTimeRangeMap = new SparseArray<JSONObject>();
							
							proDialog.setMessage("正在查詢附近的活動...");
							for (int i=0; i<dataJsonArr.length(); i++) {
								String id = dataJsonArr.getJSONObject(i).getString("uid");
								String name = dataJsonArr.getJSONObject(i).getString("name");
								
								friendList.add(new FBUser(id, name, null));
								positionTimeRangeMap.put(i, findTimeRangeJsonObj.get(id));
							}
							shakeFragmentsList.add(new WhoHaveTimeFragment(positionTimeRangeMap, friendList));
							gMap.setMyLocationEnabled(true);
							gMap.setOnMyLocationChangeListener(new loChangeListener());
						} catch (JSONException e) {
							e.printStackTrace();
						}
					}
					
					private class loChangeListener implements OnMyLocationChangeListener {
				    	private boolean haveGetLocation = false;

						@Override
						public void onMyLocationChange(Location location) {
							if (!haveGetLocation) {
								new GetActivities(location).execute();
								haveGetLocation = true;
							}
						}
						
						private class GetActivities extends AsyncTask<Void, Void, String> {
							private Location location;

							public GetActivities(Location location) {
								this.location = location;
							}

							@Override
							protected String doInBackground(Void... params) {
								String jsonStr = null;
								
								try {
									HttpResponse resp = HttpHelper.executePost(
											"http://iculture.twgg.org/activity/getAllActivities.php");
									jsonStr = EntityUtils.toString(resp.getEntity());
								} catch (ParseException e) {
									e.printStackTrace();
								} catch (IOException e) {
									e.printStackTrace();
								}
								return jsonStr;
							}
							
							private class ActivitiesQueueComparator implements Comparator<IcultureActivity> {

								@Override
								public int compare(IcultureActivity thisAc, IcultureActivity otherAc) {
									if (thisAc.getDistance() > otherAc.getDistance())
										return 1;
									else if (thisAc.getDistance() == otherAc.getDistance())
										return 0;
									else
										return -1;
								}
							}
							
							@Override
							protected void onPostExecute(String result) {
								try {
									JSONArray respJsonArr = new JSONArray(result);
									float[] distanceArr = new float[1];
									Queue<IcultureActivity> activitiesQueue =
											new PriorityQueue<IcultureActivity>(300, new ActivitiesQueueComparator());
									List<IcultureActivity> acList = new ArrayList<IcultureActivity>(300);
									
									for (int i=0; i<respJsonArr.length(); i++) {
										JSONObject activityJsonObj = respJsonArr.getJSONObject(i);
										double nowLatitude = location.getLatitude();
										double nowLongitude = location.getLongitude();
										double activityLatitude = activityJsonObj.getDouble("latitude");
										double activityLongitude = activityJsonObj.getDouble("longitude");
										String title = activityJsonObj.getString("title");
										String locationName = activityJsonObj.getString("locationName");
										String location = activityJsonObj.getString("location");
										String time = activityJsonObj.getString("startEndTime");
										String imageUrl = activityJsonObj.getString("imageUrl");
										int distance;
										
										Location.distanceBetween(nowLatitude, nowLongitude, activityLatitude, activityLongitude, distanceArr);
										distance = Math.round(distanceArr[0]);
										if (distance < 10000) {
											activitiesQueue.add(new IcultureActivity(
													title, locationName, location, time, imageUrl, distance));
										}
									}
									while (!activitiesQueue.isEmpty()) {
										IcultureActivity ac = activitiesQueue.poll();
										
										acList.add(ac);
									}
									shakeFragmentsList.add(new NearActivitiesFragment(acList));
									shakeResultPager.getAdapter().notifyDataSetChanged();
									proDialog.cancel();
									buttonGoGroup.setVisibility(View.VISIBLE);
								} catch (JSONException e) {
									e.printStackTrace();
								}
							}
						}
				    }
				}
			}
		}
	}
	
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		if (resultCode == RESULT_OK) {
			switch (requestCode) {
				default:
					Session.getActiveSession().onActivityResult(this, requestCode, resultCode, data);
			}
		}
	}
}
